package com.castle.fortress.admin.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.castle.fortress.admin.system.dto.OssPlatFormDto;
import com.castle.fortress.admin.system.service.OssService;
import com.castle.fortress.admin.utils.MinioUtil;
import com.castle.fortress.common.entity.RespBody;
import com.castle.fortress.common.exception.BizException;
import com.castle.fortress.common.respcode.BizErrorCode;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * MinIO 服务实现类
 * @author castle
 */
public class OssMinioServiceImpl implements OssService {
    private MinioUtil minioUtil;
    private OssPlatFormDto ossPlatFormDto;

    public OssMinioServiceImpl(OssPlatFormDto ossPlatFormDto, MinioUtil minioUtil) {
        this.ossPlatFormDto = ossPlatFormDto;
        this.minioUtil = minioUtil;
        // 配置 MinioUtil
        if (minioUtil != null) {
            setupMinioUtil();
        }
    }

    /**
     * 使用 OssPlatFormDto 中的配置初始化 MinioUtil
     */
    private void setupMinioUtil() {
        minioUtil.setCredentials(
            ossPlatFormDto.getEndpoint(),
            ossPlatFormDto.getAccessKey(),
            ossPlatFormDto.getSecretKey()
        );
        minioUtil.setBucketName(ossPlatFormDto.getBucketName());
    }

    @Override
    public RespBody putFile(byte[] content, String fileName) {
        try {
            // 确保 MinioUtil 配置正确
            if (minioUtil == null) {
                throw new BizException(BizErrorCode.FT_MINIO_ERROR);
            }
            setupMinioUtil();

            // 处理文件名编码，确保中文字符正确显示
            String encodedFileName = new String(fileName.getBytes("ISO-8859-1"), "UTF-8");
            // 创建独立的 BucketName+文件名上传接口
            String uniqueFileName = generateUniqueFileName(encodedFileName);

            // 自定义上传逻辑
            uploadByteArray(content, uniqueFileName);

            // 构建返回结果
            Map<String, Object> response = new HashMap<>();
            String fileUrl = minioUtil.getFileUrl(minioUtil.getBucketName(), uniqueFileName);
            response.put("url", fileUrl);
            response.put("path", fileUrl);
            response.put("fileName", uniqueFileName);
            response.put("originalFileName", encodedFileName);

            return RespBody.data(response);
        } catch (Exception e) {
            throw new BizException(BizErrorCode.FT_UPLOAD_ERROR);
        }
    }

    @Override
    public RespBody putFile(File file) {
        try {
            // 确保 MinioUtil 配置正确
            if (minioUtil == null) {
                throw new BizException(BizErrorCode.FT_MINIO_ERROR);
            }
            setupMinioUtil();

            // 处理文件名编码，确保中文字符正确显示
            String encodedFileName = new String(file.getName().getBytes("ISO-8859-1"), "UTF-8");
            // 生成唯一文件名
            String uniqueFileName = generateUniqueFileName(encodedFileName);

            // 自定义上传逻辑
            try (FileInputStream fis = new FileInputStream(file)) {
                byte[] bytes = new byte[(int) file.length()];
                fis.read(bytes);
                uploadByteArray(bytes, uniqueFileName);

                // 构建返回结果
                Map<String, Object> response = new HashMap<>();
                String fileUrl = minioUtil.getFileUrl(minioUtil.getBucketName(), uniqueFileName);
                response.put("url", fileUrl);
                response.put("path", fileUrl);
                response.put("fileName", uniqueFileName);
                response.put("originalFileName", encodedFileName);

                return RespBody.data(response);
            }
        } catch (Exception e) {
            throw new BizException(BizErrorCode.FT_UPLOAD_ERROR);
        }
    }

    @Override
    public RespBody putFile(MultipartFile file) {
        try {
            // 确保 MinioUtil 配置正确
            if (minioUtil == null) {
                throw new BizException(BizErrorCode.FT_MINIO_ERROR);
            }
            setupMinioUtil();

            // 处理原始文件名编码
            String originalFileName = file.getOriginalFilename();
            if (originalFileName != null) {
                originalFileName = new String(originalFileName.getBytes("ISO-8859-1"), "UTF-8");
            }

            // 使用 MinioUtil 的 putObject 方法直接上传文件
            Map<String, String> result = minioUtil.putObject(file);

            // 覆盖MinioUtil可能未处理的encodedOriginalFileName
            if (originalFileName != null) {
                result.put("originalFileName", originalFileName);
            }

            // 构建返回结果
            Map<String, Object> response = new HashMap<>();
            response.put("url", result.get("fileUrl"));
            response.put("path", result.get("fileUrl"));
            response.put("fileName", result.get("fileName"));
            response.put("originalFileName", result.get("originalFileName"));

            return RespBody.data(response);
        } catch (Exception e) {
            throw new BizException(BizErrorCode.FT_UPLOAD_ERROR);
        }
    }

    /**
     * 上传字节数组到 MinIO
     */
    private void uploadByteArray(byte[] content, String fileName) throws Exception {
        try (InputStream inputStream = new ByteArrayInputStream(content)) {
            minioUtil.getMinioClient().putObject(
                io.minio.PutObjectArgs.builder()
                    .bucket(minioUtil.getBucketName())
                    .object(fileName)
                    .stream(inputStream, content.length, -1)
                    .contentType(getContentType(fileName))
                    .build()
            );
        }
    }

    /**
     * 根据文件名推断内容类型
     */
    private String getContentType(String fileName) {
        try {
            return java.nio.file.Files.probeContentType(java.nio.file.Paths.get(fileName));
        } catch (IOException e) {
            // 默认返回二进制流
            return "application/octet-stream";
        }
    }


    /**
     * 生成唯一文件名
     */
    private String generateUniqueFileName(String originalFileName) {
        // 提取文件扩展名
        String extension = getFileExtension(originalFileName);
        String timestamp = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        String randomStr = RandomUtil.randomString(6);
        return timestamp + randomStr + "." + extension;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (fileName == null) {
            return "";
        }
        int lastIndexOfDot = fileName.lastIndexOf(".");
        if (lastIndexOfDot == -1) {
            return ""; // 没有扩展名
        }
        return fileName.substring(lastIndexOfDot + 1);
    }
}
